package com.ecarx.camera.worker.car.adaptapi;

import android.util.SparseIntArray;

import com.ecarx.camera.utils.LogUtils;
import com.ecarx.camera.utils.Utils;
import com.ecarx.camera.worker.car.constant.IllegalData;
import com.ecarx.xui.adaptapi.automotive.VehicleArea;
import com.ecarx.xui.adaptapi.automotive.VehiclePropertyGroup;
import com.ecarx.xui.adaptapi.automotive.VehiclePropertyType;
import com.ecarx.xui.adaptapi.car.Car;
import com.ecarx.xui.adaptapi.car.IWrapper;
import com.ecarx.xui.adaptapi.car.dvr.IDvr;

import java.util.ArrayList;
import java.util.List;

/**
 * AdaptAPI的IWrapper的助手类（用于将AdaptAPI定义的functionId/sensorId和value转化成AOSP原生的id和value）
 */
public class AdaptWrapperHelper {

    /**
     * 是否直接使用本地propertyId映射（fixme: 正式发版本时，需要修改成false）
     */
    private static final boolean USE_LOCAL_PROPERTY_ID_MAP = false;

    private static final String TAG = "AdaptWrapperHelper";

    // 0x21400000
    private static final int PROP_ID_MASK = VehiclePropertyGroup.VENDOR|VehiclePropertyType.INT32|VehicleArea.GLOBAL;
    private static final SparseIntArray FUNCTION_ID_MAP = new SparseIntArray();
    static {
        FUNCTION_ID_MAP.put(IDvr.DVR_FUNC_GENERAL_RECORDING_DURATION, 0x713b|PROP_ID_MASK);
        FUNCTION_ID_MAP.put(IDvr.DVR_FUNC_GENERAL_RECORDING_MIC_MUTE, 0x713c|PROP_ID_MASK);
        FUNCTION_ID_MAP.put(IDvr.DVR_FUNC_CAMERA_OPERATION, 0x71c9|PROP_ID_MASK);
        FUNCTION_ID_MAP.put(IDvr.DVR_FUNC_CAMERA_OPERATION_STATUS, 0x71ca|PROP_ID_MASK);
        FUNCTION_ID_MAP.put(IDvr.DVR_FUNC_CURRENT_STATUS, 0x71cb|PROP_ID_MASK);
        FUNCTION_ID_MAP.put(IDvr.DVR_FUNC_VIDEO_RESOLUTION, 0x71cc|PROP_ID_MASK);
        FUNCTION_ID_MAP.put(IDvr.DVR_FUNC_SDCARD_FORMAT, 0x71cd|PROP_ID_MASK);
        FUNCTION_ID_MAP.put(IDvr.DVR_FUNC_SDCARD_FORMAT_STATUS, 0x71ce|PROP_ID_MASK);
        FUNCTION_ID_MAP.put(IDvr.DVR_FUNC_FACTORY_RESET, 0x71cf|PROP_ID_MASK);
        FUNCTION_ID_MAP.put(IDvr.DVR_FUNC_FACTORY_RESET_STATUS, 0x71d0|PROP_ID_MASK);
        FUNCTION_ID_MAP.put(IDvr.DVR_FUNC_MODEL_NAME, 0x71d1|PROP_ID_MASK);
        FUNCTION_ID_MAP.put(IDvr.DVR_FUNC_SOFTWARE_VERSION, 0x71d2|PROP_ID_MASK);
        FUNCTION_ID_MAP.put(IDvr.DVR_FUNC_SDCARD_USED_PERCENTAGE, 0x71d3|PROP_ID_MASK);
        FUNCTION_ID_MAP.put(IDvr.DVR_FUNC_SDCARD_STATUS, 0x71d4|PROP_ID_MASK);
        FUNCTION_ID_MAP.put(IDvr.DVR_FUNC_EMMC_STATE, 0x71d5|PROP_ID_MASK);
        FUNCTION_ID_MAP.put(IDvr.DVR_FUNC_OPEN_EXIT, 0x71d6|PROP_ID_MASK);
        FUNCTION_ID_MAP.put(IDvr.DVR_FUNC_WAKEUP_ETHERNET, 0x71d7|PROP_ID_MASK);
    }

    /**
     * 不需要检测active的functionIds（这些functionId只支持SET操作，无法通过CarPropertyManager的isPropertyAvailable方法判断是否可用）
     */
    private static final ArrayList<Integer> NO_NEED_CHECK_ACTIVE_FUNCTION_IDS = new ArrayList<>();
    static {
        NO_NEED_CHECK_ACTIVE_FUNCTION_IDS.add(IDvr.DVR_FUNC_CAMERA_OPERATION);
        NO_NEED_CHECK_ACTIVE_FUNCTION_IDS.add(IDvr.DVR_FUNC_SDCARD_FORMAT);
        NO_NEED_CHECK_ACTIVE_FUNCTION_IDS.add(IDvr.DVR_FUNC_FACTORY_RESET);
        NO_NEED_CHECK_ACTIVE_FUNCTION_IDS.add(IDvr.DVR_FUNC_OPEN_EXIT);
    }

    private static IWrapper sAdaptAPIWrapper;

    /**
     * 将AdaptAPI中定义的functionId转化为aosp中对应的propertyId
     * @param adaptFunctionId AdaptAPI中定义的functionId
     * @return aosp中对应的propertyId
     */
    public static int functionIdToPropertyId(int adaptFunctionId) {
        if (USE_LOCAL_PROPERTY_ID_MAP) {
            int propId = FUNCTION_ID_MAP.get(adaptFunctionId, adaptFunctionId);
            LogUtils.d(TAG, "functionIdToPropertyId, adaptFunctionId:" + adaptFunctionId + ", propertyId:0x" + Integer.toHexString(propId));
            return propId;
        }
        final IWrapper.IPropertyId propertyId = getFunctionWrapperPropertyId(adaptFunctionId);
        if (propertyId == null) {
            LogUtils.w(TAG, "functionIdToPropertyId, adaptFunctionId:" + adaptFunctionId + ", propertyId is null");
            return adaptFunctionId;
        }
        int proId = propertyId.getPropertyId();
        LogUtils.d(TAG, "functionIdToPropertyId, adaptFunctionId:" + adaptFunctionId + ", propertyId:0x" + Integer.toHexString(proId));
        return proId;
    }

    /**
     * 将AdaptAPI中定义的value转化为aosp中定义的value
     * @param adaptFunctionId AdaptAPI中定义的functionId
     * @param adaptFunctionValue AdaptAPI中定义的value
     * @return Aosp中定义的value
     */
    public static int functionValueToPropertyValue(int adaptFunctionId, int adaptFunctionValue) {
        if (USE_LOCAL_PROPERTY_ID_MAP) {
            return adaptFunctionValue;
        }
        final IWrapper.IPropertyId propertyId = getFunctionWrapperPropertyId(adaptFunctionId);
        if (propertyId == null) {
            LogUtils.w(TAG, "functionValueToPropertyValue, adaptFunctionId:" + adaptFunctionId + ", adaptFunctionValue:" + adaptFunctionValue +  ", propertyId is null");
            return adaptFunctionValue;
        }
        Integer propertyValue = propertyId.getPropertyValue(adaptFunctionValue);
        if (propertyValue == null) {
            LogUtils.w(TAG, "functionValueToPropertyValue, adaptFunctionId:" + adaptFunctionId + ", adaptFunctionValue:" + adaptFunctionValue +  ", propertyValue is null");
            return adaptFunctionValue;
        }
        LogUtils.d(TAG, "functionValueToPropertyValue, adaptFunctionId:" + adaptFunctionId + ", adaptFunctionValue:" + adaptFunctionValue +  ", propertyValue:" + propertyValue);
        return propertyValue;
    }

    /**
     * 将Aosp中返回的value转化为AdaptAPI中定义的value
     * @param adaptFunctionId AdaptAPI中定义的functionId
     * @param propertyValue Aosp中返回的value
     * @return AdaptAPI中定义的value
     */
    public static int propertyValueToFunctionValue(int adaptFunctionId, Integer propertyValue) {
        if (propertyValue == null) {
            return IllegalData.FunctionIllegalValue.NULL_VALUE;
        }
        if (USE_LOCAL_PROPERTY_ID_MAP) {
            return propertyValue;
        }
        final IWrapper.IPropertyId propertyId = getFunctionWrapperPropertyId(adaptFunctionId);
        if (propertyId == null) {
            LogUtils.w(TAG, "propertyValueToFunctionValue, adaptFunctionId:" + adaptFunctionId + ", propertyValue:" + propertyValue + ", propertyId is null");
            return propertyValue;
        }
        Integer adaptValue = propertyId.getPropertyAdaptValue(propertyValue);
        if (adaptValue == null) {
            LogUtils.w(TAG, "propertyValueToFunctionValue, adaptFunctionId:" + adaptFunctionId + ", propertyValue:" + propertyValue + ", adaptValue is null");
            return propertyValue;
        }
        LogUtils.d(TAG, "propertyValueToFunctionValue, adaptFunctionId:" + adaptFunctionId + ", propertyValue:" + propertyValue + ", adaptValue:" + adaptValue);
        return adaptValue;
    }

    /**
     * 将AdaptAPI中定义的sensorId转化为aosp中对应的propertyId
     * @param adaptSensorId AdaptAPI中定义的sensorId
     * @return aosp中对应的propertyId
     */
    public static int sensorIdToPropertyId(int adaptSensorId) {
        final IWrapper.IPropertyId propertyId = getSensorWrapperPropertyId(adaptSensorId);
        if (propertyId == null) {
            LogUtils.w(TAG, "sensorIdToPropertyId, adaptSensorId:" + adaptSensorId + ", propertyId is null");
            return adaptSensorId;
        }
        int propId = propertyId.getPropertyId();
        LogUtils.d(TAG, "sensorIdToPropertyId, adaptSensorId:" + adaptSensorId + ", propertyId:0x" + Integer.toHexString(propId));
        return propId;
    }

    /**
     * 将AdaptAPI中定义的value转化为aosp中定义的value
     * @param adaptSensorId AdaptAPI中定义的sensorId
     * @param adaptSensorValue AdaptAPI中定义的value
     * @return Aosp中定义的value
     */
    public static int sensorValueToPropertyValue(int adaptSensorId, int adaptSensorValue) {
        final IWrapper.IPropertyId propertyId = getSensorWrapperPropertyId(adaptSensorId);
        if (propertyId == null) {
            LogUtils.w(TAG, "sensorValueToPropertyValue, adaptSensorId:" + adaptSensorId + ", adaptSensorValue:" + adaptSensorValue + ", propertyId is null");
            return adaptSensorValue;
        }
        Integer propertyValue = propertyId.getPropertyValue(adaptSensorValue);
        if (propertyValue == null) {
            LogUtils.w(TAG, "sensorValueToPropertyValue, adaptSensorId:" + adaptSensorId + ", adaptSensorValue:" + adaptSensorValue + ", propertyValue is null");
            return adaptSensorValue;
        }
        LogUtils.d(TAG, "sensorValueToPropertyValue, adaptSensorId:" + adaptSensorId + ", adaptSensorValue:" + adaptSensorValue + ", propertyValue:" + propertyValue);
        return propertyValue;
    }

    /**
     * 将Aosp中返回的value转化为AdaptAPI中定义的value
     * @param adaptSensorId AdaptAPI中定义的sensorId
     * @param propertyValue Aosp中返回的value
     * @return AdaptAPI中定义的value
     */
    public static int propertyValueToSensorValue(int adaptSensorId, int propertyValue) {
        final IWrapper.IPropertyId propertyId = getSensorWrapperPropertyId(adaptSensorId);
        if (propertyId == null) {
            LogUtils.w(TAG, "propertyValueToSensorValue, adaptSensorId:" + adaptSensorId + ", propertyValue:" + propertyValue + ", propertyId is null");
            return propertyValue;
        }
        Integer adaptValue = propertyId.getPropertyAdaptValue(propertyValue);
        if (adaptValue == null) {
            LogUtils.w(TAG, "propertyValueToSensorValue, adaptSensorId:" + adaptSensorId + ", propertyValue:" + propertyValue + ", adaptValue is null");
            return IllegalData.SensorIllegalValue.SENSOR_EVENT_UNKNOWN;
        }
        LogUtils.d(TAG, "propertyValueToSensorValue, adaptSensorId:" + adaptSensorId + ", propertyValue:" + propertyValue + ", adaptValue:" + adaptValue);
        return adaptValue;
    }

    /**
     * 获取所有FunctionId
     * @return
     */
    public static List<Integer> getAllFunctionIds() {
        ArrayList<Integer> result = new ArrayList<>();
        int size = FUNCTION_ID_MAP.size();
        for (int i = 0; i < size; i++) {
            result.add(FUNCTION_ID_MAP.keyAt(i));
        }
        return result;
    }

    /**
     * 判断是否不需要检测是否active
     * @param functionId
     * @return
     */
    public static boolean isNotNeedCheckActive(int functionId) {
        return NO_NEED_CHECK_ACTIVE_FUNCTION_IDS.contains(functionId);
    }

    private static IWrapper.IPropertyId getFunctionWrapperPropertyId(int adaptFunctionId) {
        return getWrapperPropertyId(IWrapper.WrappedIdType.ID_TYPE_FUNCTION, adaptFunctionId);
    }

    private static IWrapper.IPropertyId getSensorWrapperPropertyId(int adaptSensorId) {
        return getWrapperPropertyId(IWrapper.WrappedIdType.ID_TYPE_SENSOR, adaptSensorId);
    }

    private static IWrapper.IPropertyId getWrapperPropertyId(int idType, int wrappedId) {
        if (sAdaptAPIWrapper == null) {
            // 注：createWrapper的实现在fwk层
            try {
                sAdaptAPIWrapper = Car.createWrapper(Utils.getApp());
                LogUtils.d(TAG, "int wrapper, application:" + Utils.getApp() + ", IWrapper:" + sAdaptAPIWrapper);
            } catch (Throwable throwable) {
                LogUtils.w(TAG, "init wrapper e:" + throwable);
            }
        }
        if (sAdaptAPIWrapper == null) {
            return null;
        }
        return sAdaptAPIWrapper.getWrappedPropertyId(idType, wrappedId);
    }
}
